/* 
 * File:   QGLSimulator.h
 * Author: jcrada
 *
 * Created on November 28, 2008, 12:15 AM
 */

#ifndef _QGLRENDERER_H
#define	_QGLRENDERER_H

#include "BulletSimulator.h"



#include <QtOpenGL/QGLWidget>
#include <QtCore/QThread>
#include <QtGui/QMouseEvent>
#include <QtCore/QReadWriteLock>
#include <iostream>

#include <btBulletDynamicsCommon.h>

namespace jcrada {

    class QGLRenderer : public QGLWidget {
        Q_OBJECT
    public:
        friend class MainWindow;

        enum eCameraMove {
            CM_ADVANCE = 1, CM_SLIDE,
            CM_AIM_HORIZONTAL, CM_AIM_VERTICAL,
            CM_RAISE
        };

        enum eMouseMode {
            MM_CAMERA = 0, MM_TRANSLATIONAL, MM_ROTATIONAL, MM_MODE_COUNT
        };
    private:
        int _mouse_x, _mouse_y;
        double _camera_eye[3];
        double _camera_aim[2];
        double _camera_eye_lock[3];
        eMouseMode _mouse_mode;
        double _sensitivity;
        int _frame_rate;
        int _cam_frame_rate;
        int _cam_frame_count;
        bool _renderable;
        bool _show_axis;
        bool _show_center_of_mass;
        bool _show_connection_points;
        bool _show_bounding_spheres;
        bool _follow_creature;
        bool _solid_draw;
        bool _black_and_white;
        bool _render_ground;
        std::vector<btRigidBody*>* _selected_body_parts;
        int _ix_rigid_body;
        bool _left_button_pressed;
        QReadWriteLock* _lock;
        
    public slots:
        virtual void initializeGL( );
        virtual void paintGL( );
        virtual void resizeGL( int width, int height );

    protected:
        virtual void render( btRigidBody *body );
        virtual void renderGround( );
        virtual void updateCamera( );
        virtual void renderAxis( );
        virtual void renderCenterOfMass( btRigidBody* body );
        virtual void renderConnectionPoints( Creature& body );
        virtual void renderSphere( const btCollisionShape *shape );
        virtual void renderBoundingSphere( const btCollisionShape *shape );
        virtual void renderBox( const btCollisionShape *shape );
        virtual void renderCone( const btCollisionShape *shape );
        virtual void renderCylinder( const btCollisionShape *shape );
        virtual void renderCapsule( const btCollisionShape *shape );

        virtual void moveCamera( eCameraMove move, GLdouble distance = 1.0 );

        virtual void dragBody( double fx, double fy, double fz );

        virtual void mousePressEvent( QMouseEvent * event );
        virtual void mouseReleaseEvent( QMouseEvent * event );
        virtual void mouseMoveEvent( QMouseEvent * event );
        virtual void wheelEvent( QWheelEvent* event );

        virtual QReadWriteLock& getLock() const{
            return *this->_lock;
        }

        virtual std::vector<btRigidBody*>& getSelectedBodyParts( ) const {
            return *this->_selected_body_parts;
        }


        virtual void setLeftButtonPressed( bool pressed ) {
            this->_left_button_pressed = pressed;
        }

        virtual bool isLeftButtonPressed( ) const {
            return this->_left_button_pressed;
        }
    public:
        static const double DEFAULT_CAMERA_X;
        static const double DEFAULT_CAMERA_Y;
        static const double DEFAULT_CAMERA_Z;

        QGLRenderer( QWidget *parent = NULL, int x = 0, int y = 0, int w = 640, int h = 480 );
        virtual ~QGLRenderer( );

        virtual void selectBodyPart( btRigidBody* body, bool maintain_selection = true );
        virtual void deselectBodyPart( const btRigidBody* body = NULL );

        static int main( int argc, char **argv );

        virtual eMouseMode getMouseMode( ) const {
            return this->_mouse_mode;
        }

        virtual bool isFollowCreature( ) const {
            return this->_follow_creature;
        }

        virtual bool isSolidDraw( ) const {
            return this->_solid_draw;
        }

        virtual bool isBlackAndWhite() const{
            return this->_black_and_white;
        }

        virtual bool isRenderGround() const{
            return this->_render_ground;
        }

        virtual bool isShowCenterOfMass( )const {
            return this->_show_center_of_mass;
        }

        virtual bool isShowBoundingSpheres( ) const {
            return this->_show_bounding_spheres;
        }

        virtual bool isShowAxis( ) const {
            return this->_show_axis;
        }

        virtual bool isShowConnectionPoints( ) const {
            return this->_show_connection_points;
        }

        virtual int getFrameRate( ) const {
            return this->_frame_rate;
        }

        virtual int getCameraFrameRate() const{
            return this->_cam_frame_rate;
        }

        virtual bool isRenderable( ) const {
            return this->_renderable;
        }

        virtual double getSensitivity( ) const {
            return this->_sensitivity;
        }

        virtual void setFrameRate( int fps ) {
            this->_frame_rate = fps;
        }

        virtual void setCameraFrameRate(int fps){
            this->_cam_frame_rate = fps;
        }

        virtual void setMouseMode( eMouseMode mode ) {
            this->_mouse_mode = mode;
        }

        virtual void setSensitivity( double sensitivity ) {
            this->_sensitivity = sensitivity;
        }

        virtual void lockCamera( ) {
            _camera_eye_lock[0] = _camera_eye[0];
            _camera_eye_lock[1] = _camera_eye[1];
            _camera_eye_lock[2] = _camera_eye[2];
        }

        virtual void setFollowCreature( bool follow ) {
            this->_follow_creature = follow;
        }

        virtual void setSolidDraw( bool solid_draw ) {
            this->_solid_draw = solid_draw;
        }

        virtual void setShowCenterOfMass( bool show ) {
            this->_show_center_of_mass = show;
        }

        virtual void setShowBoundingSpheres( bool show ) {
            this->_show_bounding_spheres = show;
        }

        virtual void setShowAxis( bool show ) {
            this->_show_axis = show;
        }

        virtual void setShowConnectionPoints( bool show ) {
            this->_show_connection_points = show;
        }

        virtual void setRenderable( bool render ) {
            this->_renderable = render;
        }

        virtual void setBlackAndWhite(bool bb){
            this->_black_and_white = bb;
        }

        virtual void setRenderGround(bool render){
            this->_render_ground = render;
        }
    };

}

#endif	/* _QGLRENDERER_H*/

